package com.cy;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 服务的消费方
 */
@EnableFeignClients //启动feign方式的调用
@SpringBootApplication
public class NacosConsumerApplication {

//    @Bean
//    public  FilterRegistrationBean sentinelFilterRegistration() {
//            FilterRegistrationBean registration = new FilterRegistrationBean();
//            registration.setFilter(new CommonFilter());
//            registration.addUrlPatterns("/*");
//            // 入口资源关闭聚合
//            registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
//            registration.setName("sentinelFilter");
//            registration.setOrder(1);
//            return registration;
//    }

    public static void main(String[] args) {
        SpringApplication.run(NacosConsumerApplication.class, args);
    }

    //当默认提供的负载均衡策略不能满足我们需求时，我们还可以基于IRule接口自己定义策略
//    @Bean
//    public IRule rule(){
//        // return new RoundRobinRule();
//        return null;//将来可以将这个null替换为自己写的负载均衡策略对象
//    }


    /**
     * @Bean注解由spring框架提供，通常应用于@Configration注解描述的类中， 用于描述方法，将方法的返回值交给spring管理。
     * 初始化RestTemplate对象(Spring提供)，基于此对象
     * 可以通过http协议调用远程服务
     */
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * @LoadBalanced描述RestTemplate时，底层再基于RestTemplate进行服务 调用时，会被一个负载均衡拦截器进行拦截，然后再基于特定的负载均衡算法
     * 进行服务调用
     */
    @Bean
    @LoadBalanced
    public RestTemplate loadBalancedRestTemplate() {
        return new RestTemplate();
    }

    @Value("${spring.application.name}")
    private String applicationName;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RestTemplate loadBalancedRestTemplate;

    @Autowired
    private LoadBalancerClient loadBalancerClient;

    @Service
    public class ConsumerService {
        @SentinelResource("doGetResource")
        public String doGetResource() {
            return "doGetResource";
        }
    }

    @RestController
    public class ConsumerController {
        @Autowired
        private ConsumerService consumerService;

        //http://ip:port/consumer/doFindById?id=10
        @GetMapping("/consumer/doFindById")
        @SentinelResource("doFindById")
        public String doFindById(
                @RequestParam(value = "id", required = false) Integer id,
                @RequestParam(value = "name", required = false) String name) {
            return "hot id is " + id;
        }

        @GetMapping("/consumer/doLoadBalanced")
        public String doRestLoadBalancedEcho() {
            consumerService.doGetResource();
            //假如RestTemplate对象由LoadBalanced注解描述，
            //在编写url时，应该用"服务名"替换ip和port
            String url = String.format("http://%s/provider/echo/%s", "nacos-provider", applicationName);
            return loadBalancedRestTemplate.getForObject(url, String.class);
        }

        private AtomicLong at = new AtomicLong(1);

        @GetMapping("/consumer/doRestEcho")
        public String doRestEcho() {
            // System.out.println("doRestEcho="+at.getAndIncrement()+"/"+System.currentTimeMillis());
            consumerService.doGetResource();
            //基于服务名获取服务实例
            ServiceInstance serviceIntance =
                    loadBalancerClient.choose("nacos-provider");
            //获取实例对应的ip地址
            String host = serviceIntance.getHost();
            //获取实例对应的端口号
            int port = serviceIntance.getPort();
            //构建url
            String url = String.format("http://%s:%s/provider/echo/%s",
                    host, port, applicationName);
            //String url="http://"+host+":"+port+"/provider/echo/"+applicationName;
            //String url="http://localhost:8081/provider/echo/"+applicationName;
            System.out.println("url=" + url);
            //return url;

            return restTemplate.getForObject(url, String.class);

        }
    }
}
